package znet

import (
	"bytes"
	"encoding/binary"
	"errors"

	"gitee.com/colin0724/zserver/utils"
	"gitee.com/colin0724/zserver/ziface"
)

type PackType uint8

const (
	_ PackType = iota
	PACK_TYPE_REQ
	PACK_TYPE_RESP
)

var magic = uint16(0xA097)
var binary_oder binary.ByteOrder

func init() {
	binary_oder = utils.GlobalObject.ByteOrder
}

//封包拆包类实例，暂时不需要成员
type DataPack struct {
	Magic uint16
	Len   uint32
	Type  PackType
}

//封包拆包实例初始化方法
func NewDataPack() *DataPack {
	return &DataPack{
		Magic: magic,
	}
}

//获取包头长度方法
func (dp *DataPack) GetHeadLen() uint32 {
	return 11
}

func (dp *DataPack) SetType(ptype PackType) {
	dp.Type = ptype
}

func (dp *DataPack) GetType() PackType {
	return dp.Type
}

//封包方法(压缩数据)
func (dp *DataPack) Pack(msg ziface.IMessage) ([]byte, error) {
	//创建一个存放bytes字节的缓冲
	dataBuff := bytes.NewBuffer([]byte{})
	if err := binary.Write(dataBuff, binary_oder, dp.Magic); err != nil {
		return nil, err
	}

	dp.Len = 5 + msg.GetDataLen() + 2
	if err := binary.Write(dataBuff, binary_oder, dp.Len); err != nil {
		return nil, err
	}

	if err := binary.Write(dataBuff, binary_oder, dp.Type); err != nil {
		return nil, err
	}

	//写msgID
	if err := binary.Write(dataBuff, binary_oder, msg.GetMsgId()); err != nil {
		return nil, err
	}

	if err := binary.Write(dataBuff, binary_oder, msg.GetSeq()); err != nil {
		return nil, err
	}

	//写data数据
	if err := binary.Write(dataBuff, binary_oder, msg.GetData()); err != nil {
		return nil, err
	}

	utils.WriteChecksum(dataBuff, binary_oder)
	return dataBuff.Bytes(), nil
}

//拆包方法(解压数据)
func (dp *DataPack) Unpack(binaryData []byte) (ziface.IMessage, error) {
	//创建一个从输入二进制数据的ioReader
	dataBuff := bytes.NewReader(binaryData)
	if err := binary.Read(dataBuff, binary_oder, &dp.Magic); err != nil {
		return nil, err
	}

	if dp.Magic != magic {
		return nil, errors.New("Bad pack, magic error")
	}

	if err := binary.Read(dataBuff, binary_oder, &dp.Len); err != nil {
		return nil, err
	}

	if err := binary.Read(dataBuff, binary_oder, &dp.Type); err != nil {
		return nil, err
	}

	//只解压head的信息，得到dataLen和msgID
	msg := &Message{DataLen: dp.Len - 7}

	//读msgID
	if err := binary.Read(dataBuff, binary_oder, &msg.Id); err != nil {
		return nil, err
	}

	if err := binary.Read(dataBuff, binary_oder, &msg.Seq); err != nil {
		return nil, err
	}

	//判断dataLen的长度是否超出我们允许的最大包长度
	if utils.GlobalObject.MaxPacketSize > 0 && msg.DataLen > utils.GlobalObject.MaxPacketSize {
		return nil, errors.New("too large msg data received")
	}

	//这里只需要把head的数据拆包出来就可以了，然后再通过head的长度，再从conn读取一次数据
	return msg, nil
}

func (dp *DataPack) CheckCrc(msg ziface.IMessage, crc []byte) bool {
	buf, err := dp.Pack(msg)
	if err != nil {
		return false
	}

	return bytes.Equal(buf[len(buf)-2:], crc)
}
